package javax.core.common.mongo;

import com.mongodb.WriteResult;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import javax.core.common.utils.GenericsUtils;
import java.io.Serializable;
import java.util.List;

/**
 * 公共dao基类
 * 定义基础的CRUD
 *
 * @author raos
 * @emil 991207823@qq.com
 * @date 2021/8/30 21:12
 */
@SuppressWarnings("unchecked")
public abstract class BaseDaoSupport<T extends Serializable, PK extends Serializable> {

    /**
     * Spring mongo 模板操作对象
     */
    private MongoTemplate mongoTemplate;

    /**
     * 操作对象
     */
    private EntityOperation<T> op;

    /**
     * 默认构造
     */
    public BaseDaoSupport() {
        try {
            Class<T> entityClass = GenericsUtils.getSuperClassGenericsType(getClass(), 0);
            op = new EntityOperation(entityClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取主键列
     *
     * @return
     */
    protected abstract String getPKColumn();

    /**
     * 获取所有数据
     *
     * @return
     */
    public List<T> getAll() {
        return mongoTemplate.findAll(op.entityClass);
    }

    /**
     * 根据id获取数据
     *
     * @param id
     * @return
     */
    public T get(PK id) {
        return (T) mongoTemplate.findById(id, op.entityClass);
    }

    /**
     * 根据条件查询数据列表
     *
     * @param queryRule
     * @return
     * @throws Exception
     */
    protected List<T> find(QueryRule queryRule) throws Exception {
        QueryRuleCriteriaBulider bulider = new QueryRuleCriteriaBulider(queryRule);
        Query query = new Query(bulider.getCriteria());
        return mongoTemplate.find(query, op.entityClass);
    }

    /**
     * 插入数据
     *
     * @param entity
     */
    public void insert(T entity) {
        mongoTemplate.insert(entity);
    }

    public T insertAndReturn(T entity) {
        mongoTemplate.insert(entity);
        return entity;
    }

    /**
     * 更新数据
     *
     * @param entity
     */
    public int update(T entity) {
        mongoTemplate.save(entity);
        return 1;
    }

    /**
     * 根据实例列表 删除所有数据
     *
     * @param datas
     */
    public void deleteAll(List<T> datas) {
        if (datas != null) {
            for (T entity : datas) {
                mongoTemplate.remove(entity);
            }
        }
    }

    /**
     * 根据主键删除数据
     *
     * @param id
     */
    public void delete(PK id) {
        Criteria criteria = Criteria.where(this.getPKColumn()).in(id);
        if (criteria == null) {
            return;
        }

        Query query = new Query(criteria);
        T entity = (T) mongoTemplate.findOne(query, op.entityClass);

        if (query != null && null != entity) {
            return;
        }

        mongoTemplate.remove(entity);
    }

    public int deleteEntity(T entity) {
        WriteResult remove = mongoTemplate.remove(entity);
        return remove.getN();
    }

    /**
     * 设置 mongoTemplate
     *
     * @param template
     */
    protected void setTemplate(MongoTemplate template) {
        this.mongoTemplate = template;
    }

}
